package genetic.population;

import genetic.interfaces.Individual;
import genetic.interfaces.Population;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class MarioPopulation<Fitness extends Comparable<Fitness>, I extends Individual<?, Fitness>> implements Population<I> {

	private class IndividualComparator<Fit extends Comparable<Fit>> implements Comparator<I>{
		@Override
		public int compare(I ind1, I ind2){
			return ind1.eval().compareTo(ind2.eval());
		}
	}

	private ArrayList<I> individuals;
	private int maxSize;
	
	private I getWorstRef(){
		return individuals.get(0);
	}
	
	private I getBestRef(){
		return individuals.get(individuals.size() - 1);
	}
	
	public MarioPopulation(int maxPopSize){
		this.maxSize = maxPopSize;
		this.individuals = new ArrayList<I>();
	}
	
	@Override
	public void init(){	}
	
	@Override
	public boolean insertIndividual(I ind) {
		if(individuals.size() < maxSize){
			individuals.add(ind);
			Collections.sort(individuals, new IndividualComparator<Fitness>());
			return true;
		}else if(ind.eval().compareTo(getWorstRef().eval()) >= 0){
			individuals.remove(getWorstRef());
			individuals.add(ind);
			Collections.sort(individuals, new IndividualComparator<Fitness>());
			return true;
		}
		return false;
	}

	@Override
	@SuppressWarnings("unchecked")
	public I[] getIndividuals() {
		return (I[]) individuals.toArray( (I[]) Array.newInstance(individuals.get(0).getClass(), individuals.size()));
	}

	@Override
	public int getNumberOfIndividuals() {
		return individuals.size();
	}

	@Override
	public void clear(){
		individuals.clear();
	}

	@Override
	@SuppressWarnings("unchecked")
	public I getBest() {
		return (I) getBestRef().copy();
	}

	@Override
	@SuppressWarnings("unchecked")
	public I getWorst() {
		return (I) getWorstRef().copy();
	}
	
}
